home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / language / ici / ici.cpi / lex.c < prev    next >
C/C++ Source or Header  |  1994-10-27  |  10KB  |  679 lines

  1. #include "parse.h"
  2. #include "file.h"
  3. #include "buf.h"
  4. #include "src.h"
  5. #include "array.h"
  6. #ifndef NOTRACE
  7. #include "trace.h"
  8. #endif
  9.  
  10. char    *buf;
  11. int    bufz;
  12.  
  13. int
  14. growbuf(n)
  15. register int    n;
  16. {
  17.     register char    *p;
  18.  
  19.     if (bufz > n)
  20.     return 0;
  21.     n = (n + 2) * 2;
  22.     if ((p = zalloc(n)) == NULL)
  23.     return 1;
  24.     if (buf != NULL)
  25.     {
  26.     memcpy(p, buf, bufz);
  27.     zfree(buf);
  28.     }
  29.     buf = p;
  30.     bufz = n - 1;
  31.     return 0;
  32. }
  33.  
  34. #ifndef NOTRACE
  35. static int ungotten = 0;
  36. #endif
  37.  
  38. int
  39. get(p, a)
  40. register parse_t    *p;
  41. register array_t    *a;
  42. {
  43.     int        c;
  44.  
  45.     if ((c = (*p->p_file->f_type->ft_getch)(p->p_file->f_file)) == '\n' || c == '\r')
  46.     {
  47.     if (c == '\n' && p->p_sol && p->p_cr)
  48.     {
  49.         /*
  50.          * This is a \n after after a \r.  That is regarded as just one
  51.          * newline.  Get the next character.
  52.          */
  53.         c = (*p->p_file->f_type->ft_getch)(p->p_file->f_file);
  54.         if (c == '\n' || c == '\r')
  55.         {
  56.         ++p->p_lineno;
  57.         p->p_cr = c == '\r';
  58.         c = '\n';
  59.         }
  60.         else
  61.         p->p_sol = 0;
  62.     }
  63.     else
  64.     {
  65.         p->p_sol = 1;
  66.         ++p->p_lineno;
  67.         p->p_cr = c == '\r';
  68.         c = '\n';
  69.     }
  70.     }
  71.     else
  72.     p->p_sol = 0;
  73.  
  74.     if (p->p_depth > 0 && a != NULL)
  75.     {
  76.     /*
  77.      * We are within a compound statement and there is a code array
  78.      * being built. Update any trailing source marker, and if there
  79.      * isn't one, add one.
  80.      */
  81.     if (a->a_top > a->a_base && issrc(a->a_top[-1]))
  82.         srcof(a->a_top[-1])->s_lineno = p->p_lineno;
  83.     else if (pushcheck(a, 1) == 0)
  84.     {
  85.         if ((*a->a_top = objof(new_src(p->p_lineno, p->p_file->f_name))) != NULL)
  86.         {
  87.         loose(*a->a_top);
  88.         ++a->a_top;
  89.         }
  90.     }
  91.     }
  92.  
  93. #ifndef NOTRACE
  94.     if (ungotten)
  95.     ungotten = 0;
  96.     else
  97.     {
  98.     if (trace_yes && (trace_flags & TRACE_LEXER) && c != EOF)
  99.     {
  100.         fprintf(stderr, "%c", c);
  101.         if (c == '\n')
  102.             fprintf(stderr,"trace: ");
  103.     }
  104.     }
  105. #endif
  106.  
  107.     return c;
  108. }
  109.  
  110. void
  111. unget(p, c)
  112. parse_t    *p;
  113. int    c;
  114. {
  115.     (*p->p_file->f_type->ft_ungetch)(c, p->p_file->f_file);
  116.     if (c == '\n')
  117.     --p->p_lineno;
  118. #ifndef NOTRACE
  119.     ungotten = 1;
  120. #endif
  121. }
  122.  
  123. int
  124. lex(p, a)
  125. parse_t    *p;
  126. array_t    *a;
  127. {
  128.     register int    c;
  129.     register int    t = 0; /* init to shut up compiler */
  130.     register int    i;
  131.     register int    fstate;
  132.     char        *s;
  133.     long        l;
  134.     double        d;
  135.  
  136.     /*
  137.      * Skip white space, in its various forms.
  138.      */
  139.     for (;;)
  140.     {
  141.     i = p->p_sol;
  142.     if ((c = get(p, a)) == '#' && i)
  143.     {
  144.         while ((c = get(p, a)) != '\n' && c != EOF)
  145.         ;
  146.         continue;
  147.     }
  148.     else if (c == '\n')
  149.         continue;
  150.  
  151.     if (c == '/')
  152.     {
  153.         if ((c = get(p, a)) != '*')
  154.         {
  155.         unget(p, c);
  156.         goto slash;
  157.         }
  158.         /*
  159.          * A comment.
  160.          */
  161.         while ((c = get(p, a)) != EOF)
  162.         {
  163.         if (c == '*')
  164.         {
  165.             if ((c = get(p, a)) == '/')
  166.             break;
  167.             unget(p, c);
  168.         }
  169.         }
  170.         continue;
  171.     }
  172.  
  173.     if (c != ' ' && c != '\t')
  174.         break;
  175.     }
  176.  
  177.     /*
  178.      * Decypher the next token.
  179.      */
  180.     switch (c)
  181.     {
  182.     case '/':
  183.     slash:
  184.     if ((c = get(p, a)) == '=')
  185.         t = T_SLASHEQ;
  186.     else
  187.     {
  188.         unget(p, c);
  189.         t = T_SLASH;
  190.     }
  191.     break;
  192.  
  193.     case EOF:
  194.     t = T_EOF;
  195.     break;
  196.  
  197.     case '$':
  198.     t = T_DOLLAR;
  199.     break;
  200.  
  201.     case '@':
  202.     t = T_AT;
  203.     break;
  204.  
  205.     case '(':
  206.     t = T_ONROUND;
  207.     break;
  208.  
  209.     case ')':
  210.     t = T_OFFROUND;
  211.     break;
  212.  
  213.     case '{':
  214.     t = T_ONCURLY;
  215.     break;
  216.  
  217.     case '}':
  218.     t = T_OFFCURLY;
  219.     break;
  220.  
  221.     case ',':
  222.     t = T_COMMA;
  223.     break;
  224.  
  225.     case '~':
  226.     if ((c = get(p, a)) == '~')
  227.     {
  228.         if ((c = get(p, a)) == '~')
  229.         t = T_3TILDE;
  230.         else if (c == '=')
  231.         t = T_2TILDEEQ;
  232.         else
  233.         {
  234.         unget(p, c);
  235.         t = T_2TILDE;
  236.         }
  237.     }
  238.     else
  239.     {
  240.         unget(p, c);
  241.         t = T_TILDE;
  242.     }
  243.     break;
  244.  
  245.     case '[':
  246.     t = T_ONSQUARE;
  247.     break;
  248.  
  249.     case ']':
  250.     t = T_OFFSQUARE;
  251.     break;
  252.  
  253.     case '.':
  254.     if ((c = get(p, a)) >= '0' && c <= '9')
  255.     {
  256.         unget(p, c);
  257.         c = '.';
  258.         i = 0;
  259.         goto alphanum;
  260.     }
  261.     unget(p, c);
  262.     t = T_DOT;
  263.     break;
  264.  
  265.     case '*':
  266.     if ((c = get(p, a)) == '=')
  267.         t = T_ASTERIXEQ;
  268.     else
  269.     {
  270.         unget(p, c);
  271.         t = T_ASTERIX;
  272.     }
  273.     break;
  274.  
  275.     case '%':
  276.     if ((c = get(p, a)) == '=')
  277.         t = T_PERCENTEQ;
  278.     else
  279.     {
  280.         unget(p, c);
  281.         t = T_PERCENT;
  282.     }
  283.     break;
  284.  
  285.     case '^':
  286.     if ((c = get(p, a)) == '=')
  287.         t = T_CARETEQ;
  288.     else
  289.     {
  290.         unget(p, c);
  291.         t = T_CARET;
  292.     }
  293.     break;
  294.  
  295.     case '+':
  296.     if ((c = get(p, a)) == '=')
  297.         t = T_PLUSEQ;
  298.     else if (c == '+')
  299.         t = T_PLUSPLUS;
  300.     else
  301.     {
  302.         unget(p, c);
  303.         t = T_PLUS;
  304.     }
  305.     break;
  306.  
  307.     case '-':
  308.     if ((c = get(p, a)) == '>')
  309.         t = T_PTR;
  310.     else if (c == '=')
  311.         t = T_MINUSEQ;
  312.     else if (c == '-')
  313.         t = T_MINUSMINUS;
  314.     else
  315.     {
  316.         unget(p, c);
  317.         t = T_MINUS;
  318.     }
  319.     break;
  320.  
  321.     case '>':
  322.     if ((c = get(p, a)) == '>')
  323.     {
  324.         if ((c = get(p, a)) == '=')
  325.         t = T_GRTGRTEQ;
  326.         else
  327.         {
  328.         unget(p, c);
  329.         t = T_GRTGRT;
  330.         }
  331.     }
  332.     else if (c == '=')
  333.         t = T_GRTEQ;
  334.     else
  335.     {
  336.         unget(p, c);
  337.         t = T_GRT;
  338.     }
  339.     break;
  340.  
  341.     case '<':
  342.     if ((c = get(p, a)) == '<')
  343.     {
  344.         if ((c = get(p, a)) == '=')
  345.         t = T_LESSLESSEQ;
  346.         else
  347.         {
  348.         unget(p, c);
  349.         t = T_LESSLESS;
  350.         }
  351.     }
  352.     else if (c == '=')
  353.     {
  354.         if ((c = get(p, a)) == '>')
  355.         t = T_LESSEQGRT;
  356.         else
  357.         {
  358.         unget(p, c);
  359.         t = T_LESSEQ;
  360.         }
  361.     }
  362.     else
  363.     {
  364.         unget(p, c);
  365.         t = T_LESS;
  366.     }
  367.     break;
  368.  
  369.     case '=':
  370.     if ((c = get(p, a)) == '=')
  371.         t = T_EQEQ;
  372.     else
  373.     {
  374.         unget(p, c);
  375.         t = T_EQ;
  376.     }
  377.     break;
  378.  
  379.     case '!':
  380.     if ((c = get(p, a)) == '=')
  381.         t = T_EXCLAMEQ;
  382.     else if (c == '~')
  383.         t = T_EXCLAMTILDE;
  384.     else
  385.     {
  386.         unget(p, c);
  387.         t = T_EXCLAM;
  388.     }
  389.     break;
  390.  
  391.     case '&':
  392.     if ((c = get(p, a)) == '&')
  393.         t = T_ANDAND;
  394.     else if (c == '=')
  395.         t = T_ANDEQ;
  396.     else
  397.     {
  398.         unget(p, c);
  399.         t = T_AND;
  400.     }
  401.     break;
  402.  
  403.     case '|':
  404.     if ((c = get(p, a)) == '|')
  405.         t = T_BARBAR;
  406.     else if (c == '=')
  407.         t = T_BAREQ;
  408.     else
  409.     {
  410.         unget(p, c);
  411.         t = T_BAR;
  412.     }
  413.     break;
  414.  
  415.     case ';':
  416.     t = T_SEMICOLON;
  417.     break;
  418.  
  419.     case '?':
  420.     t = T_QUESTION;
  421.     break;
  422.  
  423.     case ':':
  424.     t = T_COLON;
  425.     break;
  426.  
  427.     case '#':
  428.     i = 0;
  429.     while ((c = get(p, a)) != '#' && c != '\n' && c != EOF)
  430.     {
  431.         if (chkbuf(i))
  432.         goto fail;
  433.         buf[i++] = c;
  434.     }
  435.     if (c == '\n')
  436.     {
  437.         error = "newline in #...#";
  438.         goto fail;
  439.     }
  440.     buf[i] = '\0';
  441.     if ((p->p_got.t_obj = objof(new_regexp(buf))) == NULL)
  442.         goto fail;
  443.     t = T_REGEXP;
  444.     break;
  445.  
  446.     case '\'':
  447.     t = T_INT;
  448.     goto chars;
  449.     case '\"':
  450.     t = T_STRING;
  451.     chars:
  452.     i = 0;
  453.     while ((c = get(p, a)) != (t == T_INT ? '\'' : '"') && c != '\n' && c!=EOF)
  454.     {
  455.         if (chkbuf(i))
  456.         goto fail;
  457.         if (c == '\\')
  458.         {
  459.         switch (c = get(p, a))
  460.         {
  461.         case '\n': continue;
  462.         case 'n': c = '\n'; break;
  463.         case 't': c = '\t'; break;
  464.         case 'v': c = '\v'; break;
  465.         case 'b': c = '\b'; break;
  466.         case 'r': c = '\r'; break;
  467.         case 'f': c = '\014'; break;
  468.         case 'a': c = '\007'; break;
  469.         case 'e': c = '\033'; break;
  470.         case '\\': break;
  471.         case '\'': break;
  472.         case '"': break;
  473.         case '?': break;
  474.  
  475.         case 'c':
  476.             c = get(p, a) & 0x1F;
  477.             break;
  478.  
  479.         case 'x':
  480.             l = 0;
  481.             while (((c = get(p, a)) >= '0' && c <= '9')
  482.             || (c >= 'a' && c <= 'f')
  483.             || (c >= 'A' && c <= 'F'))
  484.             {
  485.             if (c >= 'a' && c <= 'f')
  486.                 c -= 'a' - 10;
  487.             else if (c >= 'A' && c <= 'F')
  488.                 c -= 'A' - 10;
  489.             else
  490.                 c -= '0';
  491.             l = l * 16 + c;
  492.             }
  493.             unget(p, c);
  494.             c = l;
  495.             break;
  496.  
  497.         default:
  498.             if (c >= '0' && c <= '7')
  499.             {
  500.             l = c - '0';
  501.             if ((c = get(p, a)) >= '0' && c <= '7')
  502.             {
  503.                 l = l * 8 + c - '0';
  504.                 if ((c = get(p, a)) >= '0' && c <= '7')
  505.                 l = l * 8 + c - '0';
  506.                 else
  507.                 unget(p, c);
  508.             }
  509.             else
  510.                 unget(p, c);
  511.             c = l;
  512.             }
  513.             else
  514.             {
  515.             error = "unknown \\ escape";
  516.             goto fail;
  517.             }
  518.         }
  519.         }
  520.         buf[i++] = c;
  521.         if (t == T_INT)
  522.         {
  523.         if (get(p, a) != '\'')
  524.         {
  525.             error = "too many chars in ' ' sequence";
  526.             goto fail;
  527.         }
  528.         break;
  529.         }
  530.     }
  531.     if (chkbuf(i))
  532.         goto fail;
  533.     buf[i] = '\0';
  534.     if (t == T_INT)
  535.     {
  536.         if (i == 0)
  537.         {
  538.         error = "newline in ' '";
  539.         goto fail;
  540.         }
  541.         p->p_got.t_int = buf[0] & 0xFF;
  542.     }
  543.     else
  544.     {
  545.         if (c == '\n')
  546.         {
  547.         error = "newline in \"...\"";
  548.         goto fail;
  549.         }
  550.         if ((p->p_got.t_obj = objof(new_name(buf, i))) == NULL)
  551.         goto fail;
  552.     }
  553.     break;
  554.  
  555.     default:
  556.     if
  557.     (
  558.         (c < '0' || c > '9')
  559.         &&
  560.         (c < 'a' || c > 'z')
  561.         &&
  562.         (c < 'A' || c > 'Z')
  563.         &&
  564.         c != '_'
  565.         &&
  566.         c != '.'
  567.     )
  568.     {
  569.         error = "lexical error";
  570.         goto fail;
  571.     }
  572.  
  573. /*
  574.  * States to keep track of passage through a floating point number.
  575.  * ddd[.ddd][e|E[+|-]ddd]
  576.  */
  577. #define    FS_NOTF        0
  578. #define    FS_ININT    1
  579. #define    FS_INFRAC    2
  580. #define    FS_POSTE    3
  581. #define    FS_INEXP    4
  582.  
  583.     i = 0;
  584.     alphanum:
  585.     fstate = c=='.' ? FS_INFRAC : c>='0' && c<='9' ? FS_ININT : FS_NOTF;
  586.     for (;;)
  587.     {
  588.         if (chkbuf(i))
  589.         goto fail;
  590.         buf[i++] = c;
  591.         c = get(p, a);
  592.         switch (fstate)
  593.         {
  594.         case FS_POSTE:
  595.         if ((c >= '0' && c <= '9') || c == '+' || c == '-')
  596.         {
  597.             fstate = FS_INEXP;
  598.             continue;
  599.         }
  600.         goto notf;
  601.  
  602.         case FS_ININT:
  603.         if (c == '.')
  604.         {
  605.             fstate = FS_INFRAC;
  606.             continue;
  607.         }
  608.         case FS_INFRAC:
  609.         if (c == 'e' || c == 'E')
  610.         {
  611.             fstate = FS_POSTE;
  612.             continue;
  613.         }
  614.         case FS_INEXP:
  615.         if (c >= '0' && c <= '9')
  616.             continue;
  617.         notf:
  618.         fstate = FS_NOTF;
  619.         case FS_NOTF:
  620.         if
  621.         (
  622.             (c >= '0' && c <= '9')
  623.             ||
  624.             (c >= 'a' && c <= 'z')
  625.             ||
  626.             (c >= 'A' && c <= 'Z')
  627.             ||
  628.             c == '_'
  629.         )
  630.             continue;
  631.         break;
  632.         }
  633.         break;
  634.  
  635.     }
  636.     unget(p, c);
  637.     if (chkbuf(i))
  638.         break;
  639.     buf[i] = '\0';
  640.     l = strtol(buf, &s, 0);
  641.     if (*s == '\0')
  642.     {
  643.         p->p_got.t_int = l;
  644.         t = T_INT;
  645.         break;
  646.     }
  647.     d = strtod(buf, &s);
  648.     if (*s == '\0')
  649.     {
  650.         p->p_got.t_float = d;
  651.         t = T_FLOAT;
  652. #if defined(MSDOS) || defined(NSFIP)
  653.         if
  654.         (
  655.         buf[1] != '\0'
  656.         ||
  657.         !(
  658.             (buf[0] >= 'a' && buf[0] <= 'z')
  659.             ||
  660.             (buf[0] >= 'A' && buf[0] <= 'Z')
  661.         )
  662.         )
  663. #endif
  664.         break;
  665.     }
  666.     if ((p->p_got.t_obj = objof(new_cname(buf))) == NULL)
  667.         goto fail;
  668.     t = T_NAME;
  669.     break;
  670.     }
  671.     p->p_got.t_what = t;
  672.     return t;
  673.  
  674. fail:
  675.     p->p_got.t_what = T_ERROR;
  676.     p->p_got.t_str = error;
  677.     return T_ERROR;
  678. }
  679.